#include <QCoreApplication>
#include <QCommandLineParser>
#include <QDebug>
#include <QDateTime>
#include <QDir>
#include <cstdio>
#include <csignal>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "medicalserver.h"
#include "databasemanager.h"

// 全局服务器指针（用于信号处理）
MedicalServer* g_server = nullptr;

// 信号处理函数（优雅退出）
void signalHandler(int signum) {
    qDebug() << "收到信号" << signum << "，准备优雅退出...";
    if (g_server) {
        g_server->stopServer();
    }
    QCoreApplication::quit();
}

// 守护进程化
bool daemonize() {
    // 第一次 fork
    pid_t pid = fork();
    if (pid < 0) {
        return false;  // fork 失败
    }
    if (pid > 0) {
        exit(0);  // 父进程退出
    }
    
    // 子进程成为会话首进程
    if (setsid() < 0) {
        return false;
    }
    
    // 忽略 SIGHUP 信号
    signal(SIGHUP, SIG_IGN);
    
    // 第二次 fork（确保进程不是会话首进程，防止获取终端）
    pid = fork();
    if (pid < 0) {
        return false;
    }
    if (pid > 0) {
        exit(0);  // 第一个子进程退出
    }
    
    // 更改工作目录到根目录（可选，但我们需要相对路径所以不改）
    // chdir("/");
    
    // 重设文件权限掩码
    umask(0);
    
    // 关闭标准输入、输出、错误
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    
    return true;
}

// 设置日志输出到文件
void setupLogging(bool isDaemon) {
    if (!isDaemon) {
        return;
    }
    
    // 确保日志目录存在
    QDir logDir("../log");
    if (!logDir.exists()) {
        logDir.mkpath(".");
    }
    
    // 生成日志文件名（带时间戳）
    QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss");
    QString logFileName = QString("../log/server_%1.log").arg(timestamp);
    
    // 打开日志文件并重定向标准输出和错误
    int logFd = open(logFileName.toStdString().c_str(), O_WRONLY | O_CREAT | O_APPEND, 0664);
    if (logFd >= 0) {
        dup2(logFd, STDOUT_FILENO);
        dup2(logFd, STDERR_FILENO);
        if (logFd > STDERR_FILENO) {
            close(logFd);
        }
        
        // 设置为行缓冲
        setvbuf(stdout, NULL, _IOLBF, 0);
        setvbuf(stderr, NULL, _IOLBF, 0);
    }
}

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);
    app.setApplicationName("智慧医疗管理系统服务器");
    app.setApplicationVersion("1.0.0");
    
    // 解析命令行参数
    QCommandLineParser parser;
    parser.setApplicationDescription("智慧医疗管理系统服务器端");
    parser.addHelpOption();
    parser.addVersionOption();
    
    // 服务器监听地址
    QCommandLineOption hostOption(QStringList() << "H" << "host",
                                  "服务器监听地址 (默认: 0.0.0.0)",
                                  "host",
                                  "0.0.0.0");
    parser.addOption(hostOption);
    
    // 服务器监听端口
    QCommandLineOption portOption(QStringList() << "P" << "port",
                                  "服务器监听端口 (默认: 8888)",
                                  "port",
                                  "8888");
    parser.addOption(portOption);
    
    // 后台运行选项（启用日志文件）
    QCommandLineOption daemonOption(QStringList() << "d" << "daemon",
                                    "后台运行模式（日志输出到文件）");
    parser.addOption(daemonOption);
    
    // 数据库配置选项
    QCommandLineOption dbHostOption(QStringList() << "dbhost",
                                    "数据库主机地址 (默认: 1.117.74.41)",
                                    "host",
                                    "1.117.74.41");
    parser.addOption(dbHostOption);
    
    QCommandLineOption dbPortOption(QStringList() << "dbport",
                                    "数据库端口 (默认: 3306)",
                                    "port",
                                    "3306");
    parser.addOption(dbPortOption);
    
    QCommandLineOption dbNameOption(QStringList() << "dbname",
                                    "数据库名称 (默认: medical_system)",
                                    "name",
                                    "medical_system");
    parser.addOption(dbNameOption);
    
    QCommandLineOption dbUserOption(QStringList() << "dbuser",
                                    "数据库用户名 (默认: medical_user)",
                                    "user",
                                    "medical_user");
    parser.addOption(dbUserOption);
    
    QCommandLineOption dbPassOption(QStringList() << "dbpass",
                                    "数据库密码 (必需)",
                                    "password");
    parser.addOption(dbPassOption);
    
    parser.process(app);
    
    // 获取配置
    bool isDaemon = parser.isSet(daemonOption);
    QString serverHost = parser.value(hostOption);
    quint16 serverPort = parser.value(portOption).toUShort();
    QString dbHost = parser.value(dbHostOption);
    int dbPort = parser.value(dbPortOption).toInt();
    QString dbName = parser.value(dbNameOption);
    QString dbUser = parser.value(dbUserOption);
    QString dbPass = parser.value(dbPassOption);
    
    // 检查必需参数
    if (dbPass.isEmpty()) {
        qDebug() << "错误: 必须提供数据库密码";
        qDebug() << "使用方法: MedicalServer --dbpass <密码>";
        qDebug() << "完整参数请使用 --help 查看";
        return -1;
    }
    
    // 如果是守护进程模式，先进行守护进程化
    if (isDaemon) {
        if (!daemonize()) {
            // daemonize失败，但此时stdout可能已经关闭，无法输出
            return -1;
        }
    }
    
    // 设置日志输出到文件（守护进程模式）
    setupLogging(isDaemon);
    
    // 打印启动信息
    qDebug() << "========================================";
    qDebug() << "智慧医疗管理系统服务器";
    qDebug() << "启动时间:" << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
    qDebug() << "========================================";
    
    qDebug() << "服务器配置:";
    qDebug() << "  运行模式:" << (isDaemon ? "后台运行（日志输出到文件）" : "前台运行");
    qDebug() << "  监听地址:" << serverHost << ":" << serverPort;
    qDebug() << "  数据库:" << dbHost << ":" << dbPort << "/" << dbName;
    qDebug() << "  数据库用户:" << dbUser;
    
    // 注册信号处理（优雅退出）
    signal(SIGINT, signalHandler);   // Ctrl+C
    signal(SIGTERM, signalHandler);  // kill命令
    signal(SIGQUIT, signalHandler);  // Ctrl+\
    signal(SIGHUP, SIG_IGN);         // 忽略终端挂断信号
    signal(SIGPIPE, SIG_IGN);        // 忽略管道破裂信号（防止客户端断开导致崩溃）
    
    qDebug() << "正在连接数据库...";
    
    // 连接数据库（带重试机制）
    int retryCount = 0;
    const int maxRetries = 3;
    while (retryCount < maxRetries) {
        if (DatabaseManager::instance().connectToDatabase(dbHost, dbPort, dbName, dbUser, dbPass)) {
            qDebug() << "数据库连接成功";
            break;
        }
        retryCount++;
        if (retryCount < maxRetries) {
            qDebug() << "数据库连接失败，" << (maxRetries - retryCount) << "次重试机会，2秒后重试...";
            sleep(2);
        } else {
            qDebug() << "数据库连接失败，已达最大重试次数，服务器退出";
            return -1;
        }
    }
    
    // 启动服务器（带异常保护）
    MedicalServer server;
    g_server = &server;
    
    qDebug() << "正在启动服务器...";
    
    try {
        if (!server.startServer(serverHost, serverPort)) {
            qDebug() << "服务器启动失败";
            return -1;
        }
        
        qDebug() << "服务器启动成功！";
        qDebug() << "服务器运行中...";
        if (!isDaemon) {
            qDebug() << "按 Ctrl+C 停止服务器";
        }
        
        // 进入事件循环
        int ret = app.exec();
        
        qDebug() << "服务器正常退出";
        return ret;
        
    } catch (const std::exception& e) {
        qDebug() << "服务器运行异常:" << e.what();
        return -1;
    } catch (...) {
        qDebug() << "服务器运行异常: 未知错误";
        return -1;
    }
}

